home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Applications / QuArK / quarkpy / qbasemgr.py < prev    next >
Text File  |  2004-01-05  |  26KB  |  641 lines

  1. """   QuArK  -  Quake Army Knife
  2.  
  3. Map and Model editor Layout managers.
  4. """
  5. #
  6. # Copyright (C) 1996-2000 Armin Rigo
  7. # THIS FILE IS PROTECTED BY THE GNU GENERAL PUBLIC LICENCE
  8. # FOUND IN FILE "COPYING.TXT"
  9. #
  10.  
  11. #$Header: /cvsroot/quark/runtime/quarkpy/qbasemgr.py,v 1.13 2003/12/17 13:58:59 peter-b Exp $
  12.  
  13.  
  14.  
  15. #
  16. # See comments in file mapmgr.py.
  17. #
  18.  
  19.  
  20. import math
  21. import quarkx
  22. import qtoolbar
  23. import qmenu
  24. from qeditor import *
  25.  
  26.  
  27. ModesHint = "|Each view can be set to one of three rendering modes :\n\nWireframe : all polygons are drawn as lines, entities as points, etc.\n\nSolid : each polygon is drawn in a single, solid color.\n\nTextured : polygon and models are displayed with their texture."
  28.  
  29. class BaseLayout:
  30.     "An abstract base class for Map and Model Editor screen layouts."
  31.  
  32.     CurrentOpenGLOwner = "NEVER"
  33.  
  34.     def __init__(self):
  35.         # debug("Creation of layout '%s'" % self.__class__.__name__)
  36.         self.clearrefs()
  37.  
  38.     def clearrefs(self):
  39.         self.rotateviews = self.views = []
  40.         self.baseviews = []
  41.         self.sblinks = []       # list of tuples (0 or 1, sourceview, 0 or 1, destview)
  42.         self.oldsblinks = None   # where 0 means horizontal and 1 means vertical
  43.         self.explorer = None
  44.         self.mpp = None
  45.         self.buttons = {}
  46.         self.toolbars = {}
  47.         self.leftpanel = None
  48.         self.full3DFX = None
  49.         self.hintcontrol = None
  50.         self.hinttext = ""
  51.         self.compass = None
  52.  
  53.    # def __del__(self):
  54.    #     debug("Destruction of layout '%s'" % self.__class__.__name__)
  55.  
  56.     def destroyscreen(self, form):
  57.         "Closes everything on the screen and clears all references."
  58.  
  59.         try:
  60.             setup = quarkx.setupsubset(self.MODE, "Layouts")
  61.             config = setup.findshortname(self.shortname)
  62.             if config is None:
  63.                 config = quarkx.newobj(self.shortname+":config")
  64.                 setup.appenditem(config)
  65.             self.writeconfig(config)
  66.             writetoolbars(self, config)
  67.  
  68.             self.releaseOpenGL(1)
  69.         finally:
  70.             for c in form.floatings():           c.close()
  71.             for c in form.mainpanel.controls():  c.close()
  72.             for c in form.toolbars():            c.close()
  73.             form.mainpanel.sections = ((),())
  74.             if self.explorer != None: self.explorer.clear()
  75.             if self.mpp      != None: self.mpp.clear()
  76.             self.clearrefs()
  77.             del self.editor
  78.  
  79.  
  80.     def setupchanged(self, level):
  81.         "Reads setup-dependant information for the layout."
  82.         if len(self.views):
  83.             if MapOption("CrossCursor", self.MODE):
  84.                 ncursor = CR_CROSS
  85.                 nhandlecursor = CR_ARROW
  86.             else:
  87.                 ncursor = CR_ARROW
  88.                 nhandlecursor = CR_CROSS
  89.             for v in self.views:
  90.                 v.cursor = ncursor
  91.                 v.handlecursor = nhandlecursor
  92.                 v.setup = None   # reload setup from default source
  93.             setup = quarkx.setupsubset(self.MODE, "Colors")
  94.             self.views[0].color = setup.getint("ViewXY")
  95.             self.views[0].darkcolor = setup.getint("SelXY")
  96.             for v in self.views[1:]:
  97.                 v.color = setup.getint("ViewXZ")
  98.                 v.darkcolor = setup.getint("SelXZ")
  99.             self.views[0].info["onsetangle"] = self.fffsetangle
  100.             self.views[0].info["onsetscale"] = self.zoombar.ScaleChanged
  101.             self.views[0].info["onsetvangle"] = self.vbar.VAngleChanged
  102.         if MapOption("NoScrollBars", self.MODE):
  103.             for v in self.views:
  104.                 v.flags = v.flags | MV_NOSCROLLBAR
  105.         else:
  106.             for v in self.views:
  107.                 v.flags = v.flags &~ MV_NOSCROLLBAR
  108.         if self.mpp is not None:
  109.             self.mpp.lock.state = (qtoolbar.selected,0)[not MapOption("PagesLocked", self.MODE)]
  110.         if level is None:
  111.             setup = quarkx.setupsubset(self.MODE, "Layouts")
  112.             config = setup.findshortname(self.shortname)
  113.             self.readtoolbars(config)
  114.             if config is not None:
  115.                 self.readconfig(config)
  116.         if self.editor is not None:
  117.             self.setgrid(self.editor)
  118.             try:
  119.                 self.buttons["linear"].state = self.editor.linearbox and qtoolbar.selected
  120.             except KeyError:
  121.                 pass
  122.             try:
  123.                 self.buttons["lockv"].state = self.editor.lockviews and qtoolbar.selected
  124.             except KeyError:
  125.                 pass
  126.         ex = self.explorer
  127.         if MapOption("TreeKeybDelay", self.MODE):
  128.             ex.flags = ex.flags &~ EF_NOKEYBDELAY
  129.         else:
  130.             ex.flags = ex.flags | EF_NOKEYBDELAY
  131.         if self.hintcontrol is not None:
  132.             self.hintcontrol.color = MapColor("ViewXY", self.MODE)
  133.         if self.compass is not None:
  134.             self.compass.setupchanged(self.MODE)
  135.  
  136.  
  137.     def updateviewproj(self):
  138.         for v in self.views:
  139.             setprojmode(v)
  140.  
  141.     def drawing(self, view):
  142.         #
  143.         # Update the map view's display limit, to know what should
  144.         # be normal or grayed out
  145.         #
  146.         self.setupdepth(view)
  147.         #
  148.         # Scroll the views whose position are linked together
  149.         #
  150.         for ifrom, linkfrom, ito, linkto in self.sblinks:
  151.             if linkfrom is view:
  152.                 pos = view.scrollbars[ifrom][0]
  153.                 if ito:      # if the dest. view is to be scrolled vertically
  154.                     linkto.scrollto(None, pos)
  155.                 else:
  156.                     linkto.scrollto(pos, None)
  157.  
  158.  
  159.     def getlayoutmenu(self, text="level"):
  160.         "Builds a default Layout menu (may be overridden)."
  161.         modhint = ModesHint + "\n\nThe commands in this menu lets you change the mode for all views at once. To set the mode of a single view, right-click on it.|intro.mapeditor.menu.html#layoutmenu"
  162.         infobaselink = "intro.mapeditor.menu.html#layoutmenu"
  163.         Mod1 = qmenu.item("&Wireframe", self.setviewmode, modhint)
  164.         Mod1.mode = "wire"
  165.         Mod2 = qmenu.item("&Solid", self.setviewmode, modhint)
  166.         Mod2.mode = "solid"
  167.         Mod3 = qmenu.item("&Textured", self.setviewmode, modhint)
  168.         Mod3.mode = "tex"
  169.         New3D = qmenu.item("New &3D window", self.new3Dwindow, "|New 3D window:\n\nThis will create a new free-floating 3D edit window. ", infobaselink)
  170.         NewOGL = qmenu.item("OpenGL view", self.toggleOpenGLwindow, "|OpenGL 3D view:\n\nThis does the same as the previous command\n'New 3D-window' but the 3D viewer uses the OpenGL standard 3D graphic library. ", infobaselink)
  171.         NewF3D = qmenu.item("Full 3D view", self.full3Dclick, "|Full 3D view:\n\nThis does the same as the 'New 3D-window' command but in full screen mode.", infobaselink)
  172.         cliphint = "|While you edit your "+text+", some parts of it may be visible on one view but not on the others. Such parts are considered to be 'out of view', and these commands control how they are displayed :\n\n'Show whole "+text+"': no out-of-view masking\n'Gray out of view': grayed out (default)\n'Hide out of view': simply hidden"
  173.         DrM1 = qmenu.item("Show &whole "+text, self.setdrawmode, cliphint, infobaselink)
  174.         DrM1.mode = DM_NORMAL
  175.         DrM2 = qmenu.item("&Gray out of view", self.setdrawmode, cliphint, infobaselink)
  176.         DrM2.mode = DM_GRAYOOV
  177.         DrM3 = qmenu.item("&Hide out of view", self.setdrawmode, cliphint, infobaselink)
  178.         DrM3.mode = DM_HIDEOOV
  179.         PanelRight = qmenu.item("Panel at &right", self.panelatright, "|Panel at right:\n\nThis will move the main panel to the right side of your screen. Unselecting this function will move it back to the left side.", infobaselink)
  180.          #
  181.          # NOTE: this menu is accessed by position in the function "layoutmenuclick"
  182.          #
  183.         return [Mod1, Mod2, Mod3, New3D, NewOGL, NewF3D, qmenu.sep, DrM1, DrM2,
  184.          DrM3, qmenu.sep, PanelRight], {"Ctrl+1":Mod1, "Ctrl+2":Mod2,
  185.          "Ctrl+3":Mod3, "Ctrl+4": New3D, "Ctrl+5": NewOGL, "Ctrl+6": NewF3D}
  186.  
  187.     def layoutmenuclick(self, menu):
  188.         common = None
  189.         if len(self.views):
  190.             test = self.baseviews[0].viewmode
  191.             for v in self.baseviews[1:]:
  192.                 if v.viewmode != test:
  193.                     break
  194.             else:
  195.                 common = test
  196.         for m in menu.items[0:3]: # position of (self.getlayoutmenu) Mod1, Mod2 and Mod3
  197.             m.state = (m.mode == common) and qmenu.radiocheck
  198.         #menu.items[4].state = (self is BaseLayout.CurrentOpenGLOwner) and qmenu.checked
  199.         for m in menu.items[7:10]: # position of (self.getlayoutmenu) DrM1, DrM2 and DrM3
  200.             m.state = (m.mode == (self.editor.drawmode&DM_MASKOOV)) and qmenu.radiocheck
  201.         menu.items[11].state = (self.leftpanel.align=="right") and qmenu.checked # position of (self.getlayoutmenu) PanelRight
  202.  
  203.  
  204.     def setviewmode(self, menu):
  205.         for v in self.baseviews:
  206.             v.viewmode = menu.mode
  207.         self.editor.lastscale = 0    # force a call to buildhandles()
  208.  
  209.     def setdrawmode(self, menu):
  210.         self.editor.drawmode = menu.mode | (self.editor.drawmode &~ DM_MASKOOV)
  211.         self.editor.savesetupinfos()
  212.         for v in self.views:
  213.             if v.viewmode == "wire":
  214.                 v.invalidate()
  215.  
  216.     def panelatright(self, menu):
  217.         self.leftpanel.align = ("right", "left")[self.leftpanel.align=="right"]
  218.  
  219.  
  220.     def close3Dwindow(self, floating, view=None):
  221.         if view is None:
  222.             view = floating.info
  223.         if view in self.views:
  224.             self.views.remove(view)
  225.             self.update3Dviews()
  226.  
  227.     def new3Dwindow(self, menu):
  228.         "Spawns a new 3D window."
  229.         floating = quarkx.clickform.newfloating(FWF_NOESCCLOSE, "3D")
  230.         view = floating.mainpanel.newmapview()
  231.         view.info = {"type": "3D"}
  232.         view.viewmode = "tex"
  233.         setprojmode(view)
  234.         self.editor.setupview(view)
  235.         floating.info = view
  236.         floating.onclose = self.close3Dwindow
  237.         floating.show()
  238.         if not (view in self.views):
  239.             self.views.append(view)
  240.         self.update3Dviews(view)
  241.  
  242.     def closeOpenGL(self):
  243.         if BaseLayout.CurrentOpenGLOwner != "NEVER":
  244.             import qopengl
  245.             qopengl.close()
  246.  
  247.     def releaseOpenGL(self, timerclose=0):
  248.         # tells the current layout manager to stop using the OpenGL view
  249.         if BaseLayout.CurrentOpenGLOwner is not self:
  250.             if not timerclose: return
  251.             if BaseLayout.CurrentOpenGLOwner is not None: return
  252.         else:
  253.             self.buttons["opengl"].state = 0
  254.             quarkx.update(self.editor.form)
  255.         import qopengl
  256.         floating = qopengl.wnd
  257.         if floating is not None:
  258.             if BaseLayout.CurrentOpenGLOwner is self:
  259.                 self.close3Dwindow(floating, qopengl.glview)
  260.                 qopengl.clearviewdeps()
  261.             #if timerclose:
  262.             #    floating.toback()
  263.             #    quarkx.settimer(qopengl.deadtest, None, 10000)
  264.         BaseLayout.CurrentOpenGLOwner = None
  265.  
  266.     def toggleOpenGLwindow(self, menu):
  267.         "Opens/closes the OpenGL window."
  268.         import qopengl
  269.         if self is BaseLayout.CurrentOpenGLOwner:
  270.             if qopengl.offscreen:
  271.                 qopengl.open(self.editor)
  272.                 nstate = qtoolbar.selected
  273.             else:
  274.                 qopengl.open(self.editor, bkgnd = 2)
  275.                 nstate = 0
  276.         else:
  277.             if BaseLayout.CurrentOpenGLOwner is not None:
  278.                 BaseLayout.CurrentOpenGLOwner.releaseOpenGL()
  279.             qopengl.open(self.editor)
  280.             view = qopengl.glview
  281.             self.editor.setupview(view)
  282.             if not (view in self.views):
  283.                 self.views.append(view)
  284.             self.update3Dviews(view)
  285.             nstate = qtoolbar.selected
  286.             BaseLayout.CurrentOpenGLOwner = self
  287.         self.buttons["opengl"].state = nstate
  288.         quarkx.update(self.editor.form)
  289.  
  290.     def closefull3DFX(self, floating):
  291.         view = floating.mainpanel.controls()[0]
  292.         view.full3DFX(0)
  293.         if view in self.views:
  294.             self.views.remove(view)
  295.             self.update3Dviews()
  296.         self.full3DFX = None
  297.  
  298.     def full3Dclick(self, menu):
  299.         "Opens the Full 3D display."
  300.         floating = self.full3DFX
  301.         if floating is None:
  302.             floating = quarkx.clickform.newfloating(0, "3D")
  303.             self.full3DFX = floating
  304.             view = floating.mainpanel.newmapview()
  305.         else:
  306.             view = floating.mainpanel.controls()[0]
  307.             if view.full3DFX(-1):    # if already opened
  308.                 self.closefull3DFX(floating)
  309.                 return
  310.         floating.rect = view.setup["FullScreenSize"]
  311.         view.info = {"type": "3D", "noclick": None}
  312.         view.viewmode = "tex"
  313.         setprojmode(view)
  314.         self.editor.setupview(view)
  315.         floating.info = view
  316.         floating.onclose = self.closefull3DFX
  317.         mode = view.full3DFX(1)
  318.         if mode!=2:
  319.             if mode==1:
  320.                 floating.close()
  321.                 return
  322.             else:
  323.                 floating.windowrect = quarkx.screenrect()
  324.                 floating.show()
  325.         if not (view in self.views):
  326.             self.views.append(view)
  327.         self.update3Dviews(view)
  328.  
  329.     def setupdepth(self, view):
  330.         pass    # abstract
  331.  
  332.     def readconfig(self, config):
  333.           # can be overridden
  334.         if self.leftpanel is not None:
  335.             self.leftpanel.align = ("right", "left")[not config["LPAtLeft"]]
  336.             i = config.getint("LeftPanel")
  337.             if i>0:
  338.                 self.leftpanel.size = i
  339.             i = config["LeftPanelV"]
  340.             if type(i) is type(()):
  341.                 self.leftpanel.sections = ((), i)
  342.         cfg = config["ViewMode"]
  343.         if type(cfg)==type("") and len(cfg)==len(self.baseviews):
  344.             for v in self.baseviews:
  345.                 try:
  346.                     v.viewmode = {"w": "wire", "s": "solid", "t": "tex"} [ cfg[0] ]
  347.                 except:
  348.                     pass
  349.                 cfg = cfg[1:]
  350.  
  351.     def writeconfig(self, config):
  352.           # can be overridden
  353.         if self.leftpanel is not None:
  354.             config["LPAtLeft"] = "1"[:self.leftpanel.align=="right"]
  355.             config.setint("LeftPanel", self.leftpanel.size)
  356.             config["LeftPanelV"] = self.leftpanel.sections[1]
  357.         if len(self.baseviews):
  358.             cfg = ""
  359.             for v in self.baseviews:
  360.                 cfg = cfg + v.viewmode[0]
  361.             config["ViewMode"] = cfg
  362.  
  363.  
  364.     def bs_multipagespanel(self, panel):
  365.         "Builds the multi-pages panel (usually bottom left)."
  366.         ico_maped=ico_dict['ico_maped']
  367.         self.explorer = panel.newexplorer()
  368.         self.explorer.flags = EF_AUTOFOCUS
  369.         self.explorer.hint = "Data displays||Data displays:\n\nThese are the various displays to help you build and organize your map.\n\nThere are five specific displays, they are:\n\nTree-view (hierarchy-view)\nSpecifics/Args-view\nPolyhedron-view\nFace-view\n3D-view\n\nFor a detailed description and use of these displays, see the infobase documents.|intro.mapeditor.dataforms.html"
  370.         page0 = qtoolbar.button(None, "Tree-view (hierarchy-view)||Tree-view (hierarchy-view):\n\nThis view displays a  list of everything in your map : entities, polyhedrons, groups, etc.\n\n You should consider it as the best way to organize your map so that you can easily find what you are looking for.\n\nUse groups (the button above) to organize your map.\nFor more information about the available object types, see the tutorials.\n\nAlso see the infobase for a more detailed description and use of this view display.", ico_maped, 8, "Tree-view (hierarchy-view)", infobaselink='intro.mapeditor.dataforms.html#treeview')
  371.         page0.pc = [self.explorer]
  372.         plist, mppages = self.bs_additionalpages(panel)
  373.         plist.insert(0, page0)
  374.         for f in mppages:
  375.             mppg = f(self, panel)
  376.             plist.append(mppg.button())
  377.         count = 0
  378.         for btn in plist:
  379.             count = count + 1
  380.             if count<=9:
  381.                 # See also qbaseeditor.BaseEditor.initquickkeys
  382.                 #
  383.                 # Split up the hint, into its components delimited by a "|".
  384.                 hintstrings = btn.hint.split("|");
  385.                 # Then alter the first flyover-hint, suffix with a "(keyboard shortcut..)" string.
  386.                 hintstrings[0] = "%s\n(keyboard shortcut: '%d')" % (hintstrings[0], count) # To indicate what is a shortcut-key
  387.                 # Put it all together again as a string, with the "|" delimiter
  388.                 try:
  389.                     def hintprefix(hint):
  390.                         return "|"+hint
  391.                     concathints = reduce(lambda x,y: x+y, map(hintprefix, hintstrings[1:]))
  392.                 except:
  393.                     concathints = ""
  394.                 # Give the modified hint-string back to btn.hint
  395.                 btn.hint = hintstrings[0] + concathints
  396.         self.mpp = MultiPanesPanel(panel, plist, 0)
  397.         self.mpp.lock = qtoolbar.button(maptogglebtn, "lock the current page||When this button is activated, QuArK no longer automatically switches between the pages when you select or unselect objects.", ico_maped, 9)
  398.         self.mpp.lock.mode = self.MODE
  399.         self.mpp.lock.tag = "PagesLocked"
  400.         self.mpp.btnpanel.buttons = self.mpp.btnpanel.buttons + [qtoolbar.padright, self.mpp.lock]
  401.  
  402.     def bs_leftpanel(self, form, right=0):
  403.         "Default-looking panel at the left or right of the screen."
  404.         ico_maped=ico_dict['ico_maped']
  405.         if right:
  406.             LeftPanel = form.mainpanel.newrightpanel(180)
  407.         else:
  408.             LeftPanel = form.mainpanel.newleftpanel(180)
  409.         self.leftpanel = LeftPanel
  410.         toppanel = LeftPanel.newpanel()
  411.         bottompanel = LeftPanel.newpanel()
  412.         bottompanel.section = (0,1)
  413.         LeftPanel.sections = ((), (0.37,))
  414.         CompassPanel = toppanel.newbottompanel(96,0)
  415.  
  416.         self.vbar = VBar(self.rotateviews, CompassPanel.newrightpanel(36,0))
  417.         self.compass = Compass(self.rotateviews, CompassPanel.newrightpanel(96,0))
  418.         self.zoombar = ZoomBar(self.views, CompassPanel.newrightpanel(16,0), self.MODE)
  419.  
  420.         if ico_maped[0][0].size[1] <= 16:
  421.             NewItem = [qtoolbar.button(self.NewItem1Click, "New item||New item:\n\nThis window contains all objects thats possible to use in the map-views and dataform-display.|intro.mapeditor.misctools.html#newmapitem", ico_objects, iiNewFolder)]
  422.         else:
  423.             NewItem = []
  424.         Trash = qtoolbar.button(self.editor.editcmdclick, "Delete selected item, just drag & drop||Delete selected item|intro.mapeditor.misctools.html#trashcan", ico_maped, 2)
  425.         Trash.cmd = "del"
  426.         Trash.ondrop = self.editor.trash1drop
  427.         Undo = qtoolbar.macrobtn("MURD", "Multiple undo/redo||Multiple undo/redo:\n\nThe icon will open up the undo/redo display. |intro.mapeditor.misctools.html#undoredo", ico_maped, 6)
  428.         NewGroup = qtoolbar.button(self.editor.editcmdclick, "New group||New group:\n\nCreates a new group in the tree-view, where you can place other objects in, so they are neatly grouped together.|intro.mapeditor.misctools.html#newgroup", ico_maped, 16)
  429.         NewGroup.cmd = "newgroup"
  430.         bb = CompassPanel.newbtnpanel(NewItem + [Trash, Undo, NewGroup])
  431.         bb.margins = (2,1)
  432.  
  433.         self.bs_multipagespanel(bottompanel)
  434.         self.bs_userobjects(toppanel)
  435.         HintPanel = bottompanel.newbottompanel(16,0)
  436.         self.hintcontrol = HintPanel.newimagectrl()
  437.         self.hintcontrol.ondraw = self.drawhint
  438.         self.hintcontrol.hint = "|Your mouse is in the hint box."
  439.  
  440.  
  441.     def setgrid(self, editor):
  442.         "Update the display on the 'grid' button."
  443.         try:
  444.             gridbtn = self.buttons["grid"]
  445.         except:
  446.             return
  447.         if editor.gridstep:
  448.             gridbtn.caption = quarkx.ftos(editor.gridstep)
  449.         else:
  450.             gridbtn.caption = "off"
  451.         gridbtn.state = editor.grid and qtoolbar.selected
  452.         quarkx.update(self.editor.form)
  453.  
  454.  
  455.     def fffsetangle(self, view):
  456.         if hasattr(self.mpp.currentpage(), "needangle"):
  457.             self.mpp.resetpage()
  458.         self.compass.AngleChanged(view)
  459.  
  460.  
  461.  
  462.     def autozoom1click(self, m):
  463.         "The zoom button, when we click on the text, not the icon."
  464.         def autozoom(list, self=self):
  465.             scale1, center1 = AutoZoom(self.views, quarkx.boundingboxof(list), scale1=self.MAXAUTOZOOM)
  466.             return (scale1 is not None) and self.editor.setscaleandcenter(scale1, center1)
  467.         autozoom([self.editor.Root]) or autozoom(self.explorer.sellist)
  468.  
  469.  
  470.     def getgridmenu(self, gridbtn):
  471.         grid = self.editor.gridstep
  472.         gridmenu = []
  473.         for g in (0,64,32,16,8,4,2,1,.5,.25,.1):
  474.             if g:
  475.                 cap = "grid \t%s" % g
  476.             else:
  477.                 cap = "no grid"
  478.             item = qmenu.item(cap, self.editor.gridmenuclick)
  479.             item.grid = g
  480.             item.state = g==grid and qmenu.radiocheck
  481.             gridmenu.append(item)
  482.         gridmenu.append(qmenu.sep)
  483.         if grid==0:
  484.             txt = "&Other..."
  485.         else:
  486.             txt = "&Other...\t%s" % quarkx.ftos(grid)
  487.         gridmenu.append(qmenu.item(txt, self.editor.customgrid))
  488.         return gridmenu
  489.  
  490.  
  491.     def screencenter(self):
  492.         pt = self.editor.interestingpoint()
  493.         if pt is None:
  494.             return self.views[0].screencenter
  495.         else:
  496.             return pt
  497.  
  498.  
  499.     def helpbtnclick(self, m):
  500.         htmldoc("")
  501.  
  502.     def update3Dviews(self, newview=None):
  503.         if newview is not None:
  504.             newview.oncameramove = self.cameramoved
  505.         self.editor.lastscale = 0    # force a call to buildhandles()
  506.         for v in self.views:
  507.             if v is not newview:
  508.                 v.info["timer"] = 1
  509.                 quarkx.settimer(RefreshView, v, 200)
  510.  
  511.     cameramoved = update3Dviews
  512.  
  513.     def postinitviews(self):
  514.         for v in self.views:
  515.             if v.info["type"] == "3D":
  516.                 v.oncameramove = self.cameramoved
  517.  
  518.     def drawhint(self, ctrl):
  519.         cv = ctrl.canvas()
  520.         cv.brushcolor = ctrl.color
  521.         if quarkx.setupsubset(SS_MAP, "Colors")["InvertedColors"]:
  522.             fg = WHITE
  523.         else:
  524.             fg = BLACK
  525.         cv.fontcolor = fg
  526.         w,h = ctrl.clientarea
  527.         #cv.penstyle = PS_CLEAR
  528.         #cv.rectangle(0,0, w,h)
  529.         w=w-1
  530.         h=h-1
  531.         cv.penstyle = PS_SOLID
  532.         bg = cv.brushcolor
  533.         cv.pencolor = quarkx.middlecolor(fg, bg, 0.5)
  534.         cv.line(0,h, 0,0)
  535.         cv.line(0,0, w,0)
  536.         cv.pencolor = quarkx.middlecolor(fg, bg, -0.3)
  537.         cv.line(w,h, 0,h)
  538.         s = self.hinttext
  539.         if s[:1] == "|":
  540.             cv.textout(13,2, "Press")
  541.             x = 14+cv.textsize("Press")[0]
  542.             cv.fontbold = 1
  543.             cv.textout(x, 2, " F1 ")
  544.             x = x+cv.textsize(" F1 ")[0]
  545.             cv.fontbold = 0
  546.             cv.textout(x, 2, "for help")
  547.             delay = 1
  548.         else:
  549.             cv.textout(4,2, s)
  550.             delay = 0
  551.         cv.line(w,0, w,h)
  552.  
  553.  
  554.     def UnlockViews(self):
  555.         if self.oldsblinks is None:
  556.             self.oldsblinks = self.sblinks
  557.         self.sblinks = []
  558.         for view in self.views:
  559.             if not view.info.has_key("custom"):
  560.                 view.info["custom"] = defsetprojmode
  561.                 view.info["oldflags"] = view.flags
  562.                 view.flags = view.flags | MV_HSCROLLBAR | MV_VSCROLLBAR
  563.  
  564.     def LockViews(self):
  565.         if self.oldsblinks is not None:
  566.             self.sblinks = self.oldsblinks
  567.             self.oldsblinks = None
  568.         scale = None
  569.         for view in self.views:
  570.             if scale is None:
  571.                 try:
  572.                     scale = view.info["scale"]
  573.                 except:
  574.                     pass
  575.             try:
  576.                 test = view.info["custom"]
  577.             except:
  578.                 continue
  579.             if test is defsetprojmode:
  580.                 view.invalidate()
  581.                 del view.info["custom"]
  582.                 view.flags = view.info["oldflags"]
  583.                 del view.info["oldflags"]
  584.         if scale is not None:
  585.             setviews(self.views, "scale", scale)
  586.  
  587.  
  588. def RefreshView(v):
  589.     try:
  590.         del v.info["timer"]
  591.     except:
  592.         pass
  593.     v.invalidate()
  594.  
  595.  
  596. class MPPage:
  597.     "A page in the multi-pages panel."
  598.  
  599.     def __init__(self, layout, panel):
  600.         self.layout = layout
  601.         self.panel = panel
  602.  
  603.     def button(self):
  604.         raise "You must override the method 'button' of the class 'MPPage'" # abstract
  605.  
  606. # ----------- REVISION HISTORY ------------
  607. #
  608. #
  609. #$Log: qbasemgr.py,v $
  610. #Revision 1.13  2003/12/17 13:58:59  peter-b
  611. #- Rewrote defines for setting Python version
  612. #- Removed back-compatibility with Python 1.5
  613. #- Removed reliance on external string library from Python scripts
  614. #
  615. #Revision 1.12  2003/07/07 07:18:31  cdunde
  616. #To correct caption exclusion error and hint display
  617. #
  618. #Revision 1.11  2003/03/24 08:58:07  cdunde
  619. #To update info and link to infobase
  620. #
  621. #Revision 1.10  2003/03/21 05:57:05  cdunde
  622. #Update infobase and add links
  623. #
  624. #Revision 1.8  2003/02/01 02:13:22  cdunde
  625. #Add items to grid selection
  626. #
  627. #Revision 1.7  2001/10/22 10:26:17  tiglari
  628. #live pointer hunt, revise icon loading
  629. #
  630. #Revision 1.6  2001/01/26 19:07:26  decker_dk
  631. #bs_multipagespanel. Better indication of keys '1'-'5', which are actually shortcut-keys to the tree-view and  alike panels.
  632. #
  633. #Revision 1.5  2000/12/17 09:43:41  decker_dk
  634. #Some comments about menu settings, as the indexes are hardcoded!
  635. #
  636. #Revision 1.4  2000/06/02 16:00:22  alexander
  637. #added cvs headers
  638. #
  639. #
  640. #
  641.